多重起動1(FindWindow1)
今日からしばらくは多重起動についての授業だ。
ミジンコゼミで教える 多重起動 は最近の 多重起動 の基本とされている FindWindow、EnumWindow、CreateMutex についてだ。
しかし実際には、多重起動 のチェックをする方法は俺が知っている限りでも10近くある。
今回紹介しないもの以外の方法ついては是非とも自分で考えてみてくれ。
早速だが、MSDN で今回の題材となる FindWindow とは何か調べてみようか。
-- MSDN より抜粋 --
指定されたクラス名とウィンドウ名を持つトップレベルウィンドウ (親を持たないウィンドウ) を探します。子ウィンドウは探しません。
HWND FindWindow(
LPCTSTR lpClassName, // pointer to class name
LPCTSTR lpWindowName // pointer to window name
);
・
・
・
全くもって何のこっちゃ状態だな。
ちょっといじったことがあるやつなら見慣れているかもしれないが、この FindWindow という API は、
指定したウィンドウタイトルを持つウィンドウ がデスクトップ上に存在するかどうかを判定する API だ。
そして FindWindow という API を使う場合、lpClassName と lpWindowName というものを指定する必要があることを説いている。
ここでウィンドウという言葉が出てきたが、こいつを理解するにはウィンドウというものの概念を分かってないといけない。
詳しくは 8日目:ウィンドウについて で説明するが、軽く説明しておこうか。
とりあえず notepad でいいから立ち上げてみろ。
多少大雑把な説明ではあるが、この notepad を形成している外側(視覚的に)の部分を親ウィンドウと呼ぶ。
notepad も含め、お前達が普段使っているプログラムはそれぞれが別々にこの親ウィンドウを持ち、形成されている。
そしてこれらウィンドウはクラスという識別値を持っているのだが、単純に学校のクラスと同じ意味で使われている値だ。
要はウィンドウというものがどのクラス(クラブと思ったほうが簡単か?)に所属しているかを判別するための名札のようなものだ。
ではそろそろFindWindow の動作を読み解こうか。おっと、notepad は閉じるなよ。
notepad のタイトルに「無題 - メモ帳」と出ているな? これをウィンドウタイトルと呼ぶ。
FindWindow を用いて「無題 - メモ帳」というタイトルを持つウィンドウがデスクトップ上に存在するかどうかを探したい場合、
lpWindowName の部分にこの「無題 - メモ帳」という文字列を代入させる。
つまり、
lpWindowName とは探したいウィンドウタイトルを指定する部分だ。
次に lpClassName だが、先ほどのウィンドウの説明で説明したとおり、
ウィンドウのクラスを指定する。
すなわち、
どのクラスに所属するウィンドウを探したいかだ。
ちなみに何も指定しなければ(0 or NULL)デスクトップ上の全てを対象とする。しかし指定しないのが一般的だな。
これらを踏まえて「無題 - メモ帳」というウィンドウタイトルを含むウィンドウを FindWindow で検索したい場合、FindWindow の
書式は以下のようになる。
FindWindow(NULL,"無題 - メモ帳")
そうそう FindWIndow などの API、関数に渡すデータ(lpClassName や lpWindowName)のことを一般的に引数と呼ぶ。覚えておけ。
では FindWindow のおおまかな説明が終わったところで、FindWindow のサンプルプログラムを用意したからダウンロードしておけ。
最初は動作確認だ。
ダウンロードした FindWindow のプログラム を2つ立ち上げてみろ。
「あぼーん」
なめてるとしかいいようが無いが、この状態でもう一度プログラムを立ち上げると2つ目には「既に起動しています」と表示されたはずだ。
つまり 多重起動のチェック がされているわけだ。
一旦プログラムを終了させ、Ollydbg で読み込んでみろ。
FindWindow に続き2つの MessageBox が確認できたはずだ。
FindWindow の引数にはさきほど説明した lpClassName(0) と lpWindowName(findwindow) の2つの引数が格納されている。
ここでちょっと注意だが、 デバッガ、というよりもアセンブリでプログラムする際には関数(API)へ渡す引数は
MSDN に書いてある引数の一番後ろから値を入れるのがルールとなる。(ちなみに先ほどの FindWindow(NULL,"無題 - メモ帳") はC言語での表記だ)
例えば nasm でプログラムを作るとこのようになる。
push dword lpWindowName
push dword lpClassName
call FindWindowA
よってアセンブリ言語で表示されるデバッガにおいてもこのように逆順で表示されている。
また、FindWindow などの APIや関数に渡すこれら引数は事前にスタックに push(格納)するのも決まりごとだ。
スタックに値を push し、call 命令で関数が呼ばれた時点でスタックのデータは関数に渡される。(pop される)
よって、今回の場合だと call FindWindow の処理がされる時にスタックに格納されていた 0(ゼロ)と findwindow という文字は
スタックから pop される事となる。
では念のため確認しておこうか、F8 を2回押し Olldbg の右下にあるスタックウィンドウを見てみろ。
0012FFBC 00000000 |Class = 0
0012FFC0 00402000 \Title = "findwindow"
スタックのアドレス 0012FFBC には 0(ゼロ)が、0012FFC0には findwindow が格納されたのが分かったはずだ。
ではもう一度 F8 を押し、FindWIndow の処理が終わったところでスタックウィンドウを確認してみろ。
見事にこれらのデータはスタック上から消えたはずだ。
では次に、
おっと、休憩の時間だ。
次はこっちの教室でやるから理解できたミジンコから移動しておけ。
|